package com.hontech.bread.device

import com.hontech.bread.R
import com.hontech.bread.store.StoreCargo
import com.hontech.bread.utils.runCPU
import com.hontech.bread.utils.stringById
import kotlinx.coroutines.delay
import serial.codec.ByteView
import serial.codec.Uint8
import serial.codec.u16
import serial.codec.u32
import java.security.MessageDigest

private const val MAX_PKG_SIZE = 240

suspend fun ota(buf: ByteArray, cb: (String) -> Unit) {
    cb(stringById(R.string.text_erase_sector))

    Conn.simpleReq(Cmd.OTA_START, arrayOf(buf.size.u32()), arrayOf(), 3500)

    cb(stringById(R.string.text_start_update))

    var index = 0
    var id = 0
    while (index < buf.size) {
        var n = buf.size - index
        if (n > MAX_PKG_SIZE) {
            n = MAX_PKG_SIZE
        }
        Conn.simpleReq(Cmd.OTA_TRANSLATE, arrayOf(id.u16(), ByteView(buf, index, n)), arrayOf())
        index += n
        id++
        cb("${stringById(R.string.text_prog)}:${index * 100 / buf.size}%")
    }
    cb(stringById(R.string.text_check))
    val md5 = runCPU {
        MessageDigest.getInstance("MD5").digest(buf)
    }
    Conn.simpleReq(Cmd.OTA_COMPLETE, arrayOf(ByteView(md5)), arrayOf())
}


suspend fun breadDownMotorBottom() {
    Conn.req(Cmd.BREAD_MOTOR_TEST, arrayOf(Uint8(0)), arrayOf())
}

suspend fun breadDownMotorTop() {
    Conn.req(Cmd.BREAD_MOTOR_TEST, arrayOf(Uint8(1)), arrayOf())
}


suspend fun deliveryLeft() {
    Conn.req(Cmd.DELIVERY_MOTOR_TEST, arrayOf(Uint8(0)), arrayOf())
}

suspend fun deliveryRight() {
    Conn.req(Cmd.DELIVERY_MOTOR_TEST, arrayOf(Uint8(1)), arrayOf())
}

suspend fun deliveryDelivery() {
    Conn.req(Cmd.DELIVERY_MOTOR_TEST, arrayOf(Uint8(2)), arrayOf())
}

suspend fun leftRotationRow(row: Int): Int {
    val state = Uint8()
    Conn.req(Cmd.ROTATION_MOTOR_TEST, arrayOf(Uint8(0), Uint8(row)), arrayOf(state))
    return state.value
}

suspend fun rightRotationRow(row: Int): Int {
    val state = Uint8()
    Conn.req(Cmd.ROTATION_MOTOR_TEST, arrayOf(Uint8(1), Uint8(row)), arrayOf(state))
    return state.value
}

suspend fun leftRotationClose() {
    Conn.req(Cmd.ROTATION_MOTOR_TEST, arrayOf(Uint8(2), Uint8(1)), arrayOf())
}

suspend fun rightRotationClose() {
    Conn.req(Cmd.ROTATION_MOTOR_TEST, arrayOf(Uint8(3), Uint8(1)), arrayOf())
}

suspend fun middlePushFront() {
    Conn.req(Cmd.MIDDLE_PUSH_MOTOR_TEST, arrayOf(Uint8(0)), arrayOf())
}

suspend fun middlePushBack() {
    Conn.req(Cmd.MIDDLE_PUSH_MOTOR_TEST, arrayOf(Uint8(1)), arrayOf())
}

suspend fun rightPushReset() {
    Conn.req(Cmd.RIGHT_PUSH_MOTOR_TEST, arrayOf(Uint8(0)), arrayOf())
}

suspend fun rightPushPush() {
    Conn.req(Cmd.RIGHT_PUSH_MOTOR_TEST, arrayOf(Uint8(1)), arrayOf())
}

suspend fun leftPushReset() {
    Conn.req(Cmd.LEFT_PUSH_MOTOR_TEST, arrayOf(Uint8(0)), arrayOf())
}

suspend fun leftPushPush() {
    Conn.req(Cmd.LEFT_PUSH_MOTOR_TEST, arrayOf(Uint8(1)), arrayOf())
}

suspend fun pickLedOn() {
    Conn.req(Cmd.PICK_LED_CTRL, arrayOf(Uint8(0)), arrayOf())
}

suspend fun pickLedOff() {
    Conn.req(Cmd.PICK_LED_CTRL, arrayOf(Uint8(1)), arrayOf())
}

suspend fun heatOn() {
    Conn.req(Cmd.HEAT_CTRL, arrayOf(Uint8(0)), arrayOf())
}

suspend fun heatOff() {
    Conn.req(Cmd.HEAT_CTRL, arrayOf(Uint8(1)), arrayOf())
}

suspend fun reset(cb: (String) -> Unit) {
    if (busyFlag) {
        throw IllegalStateException("${stringById(R.string.t1733460848_240)}")
    }
    busyFlag = true

    try {
        resetImpl(cb)
    } finally {
        busyFlag = false

        leftRotationClose()
        rightRotationClose()
    }
}

private suspend fun resetImpl(cb: (String) -> Unit) {
    cb("${stringById(R.string.t1733460848_241)}")
    leftPushReset()
    cb("${stringById(R.string.t1733460848_242)}")
    rightPushReset()
    cb("${stringById(R.string.t1733460848_243)}")
    middlePushBack()
    cb("${stringById(R.string.t1733460848_244)}")
    breadDownMotorTop()
    cb("${stringById(R.string.t1733460848_245)}")
    deliveryLeft()
    cb("${stringById(R.string.t1733460848_246)}")
    leftRotationRow(1)
    cb("${stringById(R.string.t1733460848_247)}")
    rightRotationRow(1)
    cb("${stringById(R.string.t1733460848_248)}")
}

fun lastRow(row: Int): Int {
    if (row == 1) {
        return StoreCargo.MAX_ROW
    }
    return row - 1
}

fun nextRow(row: Int): Int {
    if (row == StoreCargo.MAX_ROW) {
        return 1
    }
    return row + 1
}

private var busyFlag = false

suspend fun deliveryAny(col: Int, row: Int, time: Long, cb: (String) -> Unit) {
    if (col == StoreCargo.LEFT_COL) {
        deliveryLeft(row, time, cb)
    } else {
        deliveryRight(row, time, cb)
    }
}

suspend fun deliveryLeft(row: Int, time: Long, cb: (String) -> Unit) {
    if (busyFlag) {
        throw IllegalStateException("${stringById(R.string.t1733460848_249)}")
    }
    busyFlag = true

    try {
        deliveryLeftImpl(row, time, cb)
    } finally {
        busyFlag = false
        leftRotationClose()
    }
}

private suspend fun deliveryLeftImpl(row: Int, time: Long, cb: (String) -> Unit) {
    cb("${stringById(R.string.t1733460848_250)}")
    leftPushReset()
    cb("${stringById(R.string.t1733460848_251)}")
    rightPushReset()
    cb("${stringById(R.string.t1733460848_252)}")
    middlePushBack()
    cb("${stringById(R.string.t1733460848_253)}")
    breadDownMotorTop()
    cb("${stringById(R.string.t1733460848_254)}")
    deliveryLeft()

    cb("${stringById(R.string.t1733460848_255)}:$row")
    val n = leftRotationRow(lastRow(row))
    if (n == 0) {
        throw IllegalStateException("${stringById(R.string.t1733460848_256)}:${row} ${stringById(R.string.t1733460848_257)}")
    }
    leftRotationRow(row)

    cb("${stringById(R.string.t1733460848_258)}")
    leftPushPush()

    cb("${stringById(R.string.t1733460848_259)}")
    leftPushReset()

    cb("${stringById(R.string.t1733460848_260)}")
    middlePushFront()

    cb("${stringById(R.string.t1733460848_261)}")
    middlePushBack()

    cb("${stringById(R.string.t1733460848_262)}")
    breadDownMotorBottom()

    delay(time)

    cb("${stringById(R.string.t1733460848_263)}")
    breadDownMotorTop()

    cb("${stringById(R.string.t1733460848_264)}")
    deliveryDelivery()

    pickLedOn()

    cb("${stringById(R.string.t1733460848_265)}")
    deliveryLeft()

    pickLedOff()
}

suspend fun deliveryRight(row: Int, time: Long, cb: (String) -> Unit) {
    if (busyFlag) {
        throw IllegalStateException("${stringById(R.string.t1733460848_266)}")
    }
    busyFlag = true
    try {
        deliveryRightImpl(row, time, cb)
    } finally {
        busyFlag = false
        rightRotationClose()
    }
}

private suspend fun deliveryRightImpl(row: Int, time: Long, cb: (String) -> Unit) {
    cb("${stringById(R.string.t1733460848_267)}")
    leftPushReset()
    cb("${stringById(R.string.t1733460848_268)}")
    rightPushReset()
    cb("${stringById(R.string.t1733460848_269)}")
    middlePushBack()
    cb("${stringById(R.string.t1733460848_270)}")
    breadDownMotorTop()
    cb("${stringById(R.string.t1733460848_271)}")
    deliveryLeft()

    cb("${stringById(R.string.t1733460848_272)}:$row")
    val n = rightRotationRow(lastRow(row))
    if (n == 0) {
        throw IllegalStateException("${stringById(R.string.t1733460848_273)}:${row}${stringById(R.string.t1733460848_274)}")
    }
    rightRotationRow(row)

    cb("${stringById(R.string.t1733460848_275)}")
    rightPushPush()

    cb("${stringById(R.string.t1733460848_276)}")
    rightPushReset()

    cb("${stringById(R.string.t1733460848_277)}")
    middlePushFront()

    cb("${stringById(R.string.t1733460848_278)}")
    middlePushBack()

    cb("${stringById(R.string.t1733460848_279)}")
    breadDownMotorBottom()

    delay(time)

    cb("${stringById(R.string.t1733460848_280)}")
    breadDownMotorTop()

    cb("${stringById(R.string.t1733460848_281)}")
    deliveryDelivery()

    pickLedOn()

    cb("${stringById(R.string.t1733460848_282)}")
    deliveryLeft()

    pickLedOff()
}




















